using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace FerrSimplicity
{
    public class UtilSpline
    {
        #region Fields
        List<Vector3> mPoints;
        bool          mClosed;
        #endregion

        #region Constructor
        public UtilSpline(bool aClosed)
        {
            mClosed = aClosed;
            mPoints = new List<Vector3>();
        }
        #endregion

        #region Methods
        public  void    AddPoint        (Vector3 aPt)
        {
            mPoints.Add(aPt);
        }
        public  Vector3 Get             (float   aPercent)
        {
            float t = aPercent - ((int)aPercent);

            int index = (int)(t * mPoints.Count);

            return CubicInterpolate(GetPoint(index - 1), GetPoint(index), GetPoint(index + 1), GetPoint(index + 2), (t * mPoints.Count - index));
        }
        private Vector3 GetPoint        (int     aIndex)
        {
            if (aIndex < mPoints.Count && aIndex >= 0)
                return mPoints[aIndex];
            else
            {
                if (mClosed)
                {
                    if (aIndex >= mPoints.Count)
                        return mPoints[aIndex - mPoints.Count];
                    else
                        return mPoints[aIndex + mPoints.Count];
                }
                else
                {
                    if (aIndex >= mPoints.Count)
                        return mPoints[mPoints.Count - 1] + (mPoints[mPoints.Count - 2] - mPoints[mPoints.Count - 1]) * (aIndex - mPoints.Count);
                    else
                        return mPoints[0] + (mPoints[1] - mPoints[0]) * (aIndex + mPoints.Count);
                }
            }
        }
        private Vector3 CubicInterpolate(Vector3 y0, Vector3 y1, Vector3 y2, Vector3 y3, float mu)
        {
            Vector3 a0, a1, a2, a3;

            float mu2 = mu * mu;
            a0 = y3 - y2 - y0 + y1;
            a1 = y0 - y1 - a0;
            a2 = y2 - y0;
            a3 = y1;

            return (a0 * mu * mu2 + a1 * mu2 + a2 * mu + a3);
        }
        #endregion

        /*public void DrawDebug(int aDetail, Matrix aTransform)
        {
            Vector3 previous = Get(0);
            Vector3 curr;
            float step = 1.0f / aDetail;
            for (int i = 1; i <= aDetail; i++)
            {
                curr = Get(i * step);
                LineManager.AddLines(Vector3.Transform(previous, aTransform), Vector3.Transform(curr, aTransform), Color.Red);
                previous = curr;
            }
        }*/
    }
}
